//-----------------------------------------------------------------------------
//
//Copyright(c) 2020, ThorsianWay Technologies Co, Ltd
//All rights reserved.
//
//IP Name       :   ifdiv
//File Name     :   float_output.v
//Module name   :   float output
//Full name     :   transfer inner data to float number 
//
//Author        :   xiang tian
//Email         :   
//Data          :   2020/5/13
//Version       :   V1.01
//
//Abstract      :   
//                  
//Called  by    :   GPU
//
//Modification history
//-----------------------------------------------------
//1.00: intial version 
//1.01: add busy port
//
//-----------------------------------------------------------------------------

//-----------------------------
//DEFINE MACRO
//-----------------------------   
module float_output(
    clk,
    rst_n,
    busy,
    en,        
    exp_mult,
    sign_mult,
    man_mult,
    exception_mult,
    iszero_mult,
    type_q,
    quetient,
    exception,
    valid
);
input             clk;
input             rst_n;
input             busy;
input             en;
input      [8:0]  exp_mult;
input             sign_mult;
input      [30:0] man_mult;
input      [2:0]  exception_mult;
input             iszero_mult;
input      [1:0]  type_q;
output reg [31:0] quetient;
output reg [2:0]  exception;
output reg        valid;            


reg [31:0] int_number;

always@*
begin
    case($signed(exp_mult))
       -1:       int_number[31:0] = 32'b0                   + (man_mult[30:28]==3'b111); 
        0:       int_number[31:0] = 32'b1                   + (man_mult[30:28]==3'b111);                   
        1:       int_number[31:0] = {31'b1,man_mult[30]}    + (man_mult[29:27]==3'b111);    
        2:       int_number[31:0] = {30'b1,man_mult[30:29]} + (man_mult[28:26]==3'b111); 
        3:       int_number[31:0] = {29'b1,man_mult[30:28]} + (man_mult[27:25]==3'b111); 
        4:       int_number[31:0] = {28'b1,man_mult[30:27]} + (man_mult[26:24]==3'b111); 
        5:       int_number[31:0] = {27'b1,man_mult[30:26]} + (man_mult[25:23]==3'b111); 
        6:       int_number[31:0] = {26'b1,man_mult[30:25]} + (man_mult[24:22]==3'b111); 
        7:       int_number[31:0] = {25'b1,man_mult[30:24]} + (man_mult[23:21]==3'b111); 
        8:       int_number[31:0] = {24'b1,man_mult[30:23]} + (man_mult[22:20]==3'b111); 
        9:       int_number[31:0] = {23'b1,man_mult[30:22]} + (man_mult[21:19]==3'b111); 
       10:       int_number[31:0] = {22'b1,man_mult[30:21]} + (man_mult[20:18]==3'b111); 
       11:       int_number[31:0] = {21'b1,man_mult[30:20]} + (man_mult[19:17]==3'b111); 
       12:       int_number[31:0] = {20'b1,man_mult[30:19]} + (man_mult[18:16]==3'b111); 
       13:       int_number[31:0] = {19'b1,man_mult[30:18]} + (man_mult[17:15]==3'b111); 
       14:       int_number[31:0] = {18'b1,man_mult[30:17]} + (man_mult[16:14]==3'b111); 
       15:       int_number[31:0] = {17'b1,man_mult[30:16]} + (man_mult[15:13]==3'b111); 
       16:       int_number[31:0] = {16'b1,man_mult[30:15]} + (man_mult[14:12]==3'b111); 
       17:       int_number[31:0] = {15'b1,man_mult[30:14]} + (man_mult[13:11]==3'b111); 
       18:       int_number[31:0] = {14'b1,man_mult[30:13]} + (man_mult[12:10]==3'b111); 
       19:       int_number[31:0] = {13'b1,man_mult[30:12]} + (man_mult[11: 9]==3'b111); 
       20:       int_number[31:0] = {12'b1,man_mult[30:11]} + (man_mult[10: 8]==3'b111); 
       21:       int_number[31:0] = {11'b1,man_mult[30:10]} + (man_mult[ 9: 7]==3'b111); 
       22:       int_number[31:0] = {10'b1,man_mult[30: 9]} + (man_mult[ 8: 6]==3'b111); 
       23:       int_number[31:0] = { 9'b1,man_mult[30: 8]} + (man_mult[ 7: 5]==3'b111); 
       24:       int_number[31:0] = { 8'b1,man_mult[30: 7]} + (man_mult[ 6: 4]==3'b111); 
       25:       int_number[31:0] = { 7'b1,man_mult[30: 6]} + (man_mult[ 5: 3]==3'b111); 
       26:       int_number[31:0] = { 6'b1,man_mult[30: 5]} + (man_mult[ 4: 2]==3'b111); 
       27:       int_number[31:0] = { 5'b1,man_mult[30: 4]} + (man_mult[ 3: 1]==3'b111); 
       28:       int_number[31:0] = { 4'b1,man_mult[30: 3]} + (man_mult[ 2: 0]==3'b111); 
       29:       int_number[31:0] = { 3'b1,man_mult[30: 2]}; 
       30:       int_number[31:0] = { 2'b1,man_mult[30: 1]}; 
       31:       int_number[31:0] = { 1'b1,man_mult[30: 0]};
       32:       int_number[31:0] = {man_mult[30:0],1'b0};
       33:       int_number[31:0] = {man_mult[29:0],2'b0}; 
       34:       int_number[31:0] = {man_mult[28:0],3'b0}; 
       35:       int_number[31:0] = {man_mult[27:0],4'b0}; 
       36:       int_number[31:0] = {man_mult[26:0],5'b0}; 
       37:       int_number[31:0] = {man_mult[25:0],6'b0}; 
       38:       int_number[31:0] = {man_mult[24:0],7'b0}; 
       39:       int_number[31:0] = {man_mult[23:0],8'b0}; 
       40:       int_number[31:0] = {man_mult[22:0],9'b0};
       41:       int_number[31:0] = {man_mult[21:0],10'b0};
       42:       int_number[31:0] = {man_mult[20:0],11'b0};
       43:       int_number[31:0] = {man_mult[19:0],12'b0}; 
       44:       int_number[31:0] = {man_mult[18:0],13'b0}; 
       45:       int_number[31:0] = {man_mult[17:0],14'b0}; 
       46:       int_number[31:0] = {man_mult[16:0],15'b0}; 
       47:       int_number[31:0] = {man_mult[15:0],16'b0}; 
       48:       int_number[31:0] = {man_mult[14:0],17'b0}; 
       49:       int_number[31:0] = {man_mult[13:0],18'b0}; 
       50:       int_number[31:0] = {man_mult[12:0],19'b0}; 
       51:       int_number[31:0] = {man_mult[11:0],20'b0};
       52:       int_number[31:0] = {man_mult[10:0],21'b0};
       53:       int_number[31:0] = {man_mult[9:0],22'b0}; 
       54:       int_number[31:0] = {man_mult[8:0],23'b0}; 
       55:       int_number[31:0] = {man_mult[7:0],24'b0}; 
       56:       int_number[31:0] = {man_mult[6:0],25'b0}; 
       57:       int_number[31:0] = {man_mult[5:0],26'b0}; 
       58:       int_number[31:0] = {man_mult[4:0],27'b0}; 
       59:       int_number[31:0] = {man_mult[3:0],28'b0}; 
       60:       int_number[31:0] = {man_mult[2:0],29'b0};
       61:       int_number[31:0] = {man_mult[1:0],30'b0};
       62:       int_number[31:0] = {man_mult[0:0],31'b0}; 
       default:  int_number[31:0] = 31'b0;                  
    endcase
end

reg [22:0] float_man;
reg [7:0]  float_exp;

always@*
begin
    case($signed(exp_mult))
       -127:     begin float_man = { 1'b1,man_mult[30: 9]}; float_exp = 8'b0; end 
       -128:     begin float_man = { 2'b1,man_mult[30:10]}; float_exp = 8'b0; end 
       -129:     begin float_man = { 3'b1,man_mult[30:11]}; float_exp = 8'b0; end 
       -130:     begin float_man = { 4'b1,man_mult[30:12]}; float_exp = 8'b0; end 
       -131:     begin float_man = { 5'b1,man_mult[30:13]}; float_exp = 8'b0; end 
       -132:     begin float_man = { 6'b1,man_mult[30:14]}; float_exp = 8'b0; end 
       -133:     begin float_man = { 7'b1,man_mult[30:15]}; float_exp = 8'b0; end 
       -134:     begin float_man = { 8'b1,man_mult[30:16]}; float_exp = 8'b0; end 
       -135:     begin float_man = { 9'b1,man_mult[30:17]}; float_exp = 8'b0; end 
       -136:     begin float_man = {10'b1,man_mult[30:18]}; float_exp = 8'b0; end 
       -137:     begin float_man = {11'b1,man_mult[30:19]}; float_exp = 8'b0; end 
       -138:     begin float_man = {12'b1,man_mult[30:20]}; float_exp = 8'b0; end 
       -139:     begin float_man = {13'b1,man_mult[30:21]}; float_exp = 8'b0; end 
       -140:     begin float_man = {14'b1,man_mult[30:22]}; float_exp = 8'b0; end 
       -141:     begin float_man = {15'b1,man_mult[30:23]}; float_exp = 8'b0; end 
       -142:     begin float_man = {16'b1,man_mult[30:24]}; float_exp = 8'b0; end 
       -143:     begin float_man = {17'b1,man_mult[30:25]}; float_exp = 8'b0; end 
       -144:     begin float_man = {18'b1,man_mult[30:26]}; float_exp = 8'b0; end 
       -145:     begin float_man = {19'b1,man_mult[30:27]}; float_exp = 8'b0; end 
       -146:     begin float_man = {20'b1,man_mult[30:28]}; float_exp = 8'b0; end 
       -147:     begin float_man = {21'b1,man_mult[30:29]}; float_exp = 8'b0; end 
       -148:     begin float_man = {22'b1,man_mult[30]};    float_exp = 8'b0; end 
       -149:     begin float_man =  23'b1;                  float_exp = 8'b0; end 
       default:  begin float_man = man_mult[30:8];          float_exp = exp_mult+8'd127; end 
    endcase
end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n) quetient <= 32'b0;
    else if(en && !busy)
    begin
        casex(type_q)
            2'b1x: quetient <= iszero_mult ? 32'b0 : {sign_mult,float_exp,float_man};
            2'b00: quetient <= int_number;
            2'b01: quetient <= sign_mult ? (~int_number[30:0] + 1'b1) :
                               int_number[30:0];
        endcase
    end
end

always @(posedge clk or negedge rst_n)
begin
    if(!rst_n) exception <= 3'b0;
    else if(en && !busy) exception <= exception_mult;    
end


always @(posedge clk or negedge rst_n)
begin
    if(!rst_n) valid <= 1'b0;
    else if(!busy) valid <= en;
end

endmodule
